﻿
// Transform3DView.cpp: CTransform3DView 类的实现
//

#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "Transform3D.h"
#endif

#include "Transform3DDoc.h"
#include "Transform3DView.h"

#include "Transformation.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CTransform3DView

IMPLEMENT_DYNCREATE(CTransform3DView, CView)

BEGIN_MESSAGE_MAP(CTransform3DView, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_KEYDOWN()
END_MESSAGE_MAP()

// CTransform3DView 构造/析构

CTransform3DView::CTransform3DView() noexcept
{
	Transformation trans;

	// 将立方体放大两百倍
	trans.SetScaleMatrix(200, 200, 200);
	for (int i = 0; i < 8; ++i)
	{
		trans.Scale(cube.points[i]);
	}

	// 将立方体中心平移回坐标系中心
	trans.SetTranslationMatrix(-100, -100, -100);
	for (int i = 0; i < 8; ++i)
	{
		trans.Translation(cube.points[i]);
	}
}

CTransform3DView::~CTransform3DView()
{
}

BOOL CTransform3DView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// CTransform3DView 绘图

void CTransform3DView::DoubleBuffer(CDC* pDC)
{
	CRect rect;
	GetClientRect(&rect);
	int width = rect.Width();
	int height = rect.Height();

	// 自定义坐标系
	pDC->SetMapMode(MM_ANISOTROPIC);					// 各向异性，图案会随窗口的长宽比例而调整自己的长宽
	pDC->SetWindowExt(width, height);					// 设置窗口范围
	pDC->SetViewportExt(width, -height);				// 设置视图大小，得到一个x轴水平向右，y轴垂直向上，原点位于视图左下角的新视图
	pDC->SetViewportOrg(width / 2, height / 2);			// 设置原点

	// 准备内存DC
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);						// 创建一个与显示DC兼容的内存DC
	CBitmap newMap;
	newMap.CreateCompatibleBitmap(pDC, width, height);	// 创建兼容内存位图
	memDC.SelectObject(&newMap);						// 将兼容位图存入内存DC
	memDC.FillSolidRect(rect, pDC->GetBkColor());		// 设置客户区背景色

	/*
	*  通过上述坐标系变换，如今的rect在新的坐标系中是如此，其原点在左下角
	*			 _______________
	*			|		rect	|
	*	 _______|_______		|
	*	|		|		|		|
	*   |		|_______|_______|
	*	|	client		|
	*	|_______________|
	*/
	rect.OffsetRect(-width / 2, -height / 2);			// 这一步的目的是将rect重新拉回客户区中

	// 自定义内存DC坐标系
	width = rect.Width();
	height = rect.Height();
	memDC.SetMapMode(MM_ANISOTROPIC);
	memDC.SetWindowExt(width, height);
	memDC.SetViewportExt(width, -height);
	memDC.SetViewportOrg(width / 2, height / 2);

	// 绘制矩形
	cube.DrawCube(&memDC);

	// 显示矩形
	/*
	*  BOOLBitBlt(int x,int y,int nWidth,int nHeight,CDC*pSrcDC,int xSrc,int ySrc,DWORD dwRop);
	*  
	*  函数描述：从源设备中复制位图到目标设备
	*  函数参数：
	*  x:		目标矩形区域的左上角X轴坐标点
	*  y:		目标矩形区域的左上角y轴坐标点
	*  nWidth:	在目标设备中绘制的位图宽度
	*  nHeight: 在目标设备中绘制的位图高度
	*  pSrcDC:	源设备上下文指针对象（CDC*）
	*  xSrc:	源设备上下文的起点x轴坐标，函数从该起点复制位图到目标设备
	*  ySrc:	源设备上下文的起点y轴坐标，函数从该起点复制位图到目标设备
	*  dwRop:	光栅操作代码
	* 
	*/
	pDC->BitBlt(rect.left, rect.top, width, height, &memDC, -width / 2, -height / 2, SRCCOPY);

	// 释放资源
	memDC.DeleteDC();
	newMap.DeleteObject();
}

void CTransform3DView::Scale(double sx, double sy, double sz)
{
	Transformation trans;
	trans.SetScaleMatrix(sx, sy, sz);

	for (int i = 0; i < 8; ++i)
	{
		trans.Scale(cube.points[i]);
	}

	Invalidate(TRUE);
}

void CTransform3DView::RotationX(int degree)
{
	Transformation trans;

	for (int i = 0; i < 8; ++i)
		trans.RotationX(degree, cube.points[i]);

	Invalidate(TRUE);
}

void CTransform3DView::RotationY(int degree)
{
	Transformation trans;

	for (int i = 0; i < 8; ++i)
		trans.RotationY(degree, cube.points[i]);

	Invalidate(TRUE);
}

void CTransform3DView::OnDraw(CDC* pDC)
{
	CTransform3DDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	DoubleBuffer(pDC);
}


// CTransform3DView 打印

BOOL CTransform3DView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CTransform3DView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CTransform3DView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// CTransform3DView 诊断

#ifdef _DEBUG
void CTransform3DView::AssertValid() const
{
	CView::AssertValid();
}

void CTransform3DView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CTransform3DDoc* CTransform3DView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTransform3DDoc)));
	return (CTransform3DDoc*)m_pDocument;
}
#endif //_DEBUG


// CTransform3DView 消息处理程序


void CTransform3DView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	/*
	*	VK_UP：			键盘上键（绕X轴向上旋转）
	*	VK_DOWN：		键盘下键（绕X轴向下旋转）
	*	VK_LEFT：		键盘左键（绕Y轴向左旋转）
	*	VK_RIGHT：		键盘右键（绕Y轴向右旋转）
	*	VK_ADD：			键盘＋键（根据原点放大）
	*	VK_SUBTRACT：	键盘-键 （根据原点缩小）
	*/
	switch (nChar)
	{
	case VK_UP:		
		RotationX(30);
		break;
	case VK_DOWN:
		RotationX(-30);
		break;
	case VK_LEFT:
		RotationY(-30);
		break;
	case VK_RIGHT:
		RotationY(30);
		break;
	case VK_ADD:
		Scale(1.25, 1.25, 1.25);
		break;
	case VK_SUBTRACT:
		Scale(0.8, 0.8, 0.8);
		break;
	default:
		break;
	}

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
